"use strict";

const ENV = require("@/ENV.js");

import Vue from 'vue';
import axios from "axios";
import VueCookies from 'vue-cookies'

Vue.use(VueCookies);


let config = {
    timeout: 10 * 60 * 1000, // Timeout 10min
    /* 让axios能使用session */
    withCredentials: true, //意思是携带cookie信息,保持session的一致性
    baseURL: ENV.axiosBaseUrl
};

const _axios = axios.create(config);


/* 取消调用链必须使用 CancelToken*/
const CancelToken = axios.CancelToken;

_axios.interceptors.request.use(
    function (config) {
        /**
         * source 方法是CancelToken的一个工厂方法
         * CancelToken.source = function source() {
         *      var cancel;
         *      var token = new CancelToken(function executor(c) {
         *          cancel = c;
         *      });
         *
         *      return {
         *          token: token,
         *          cancel: cancel
         *      };
         * };
         * @type {CancelTokenSource}
         */
        /** source == {
         *               token: token,
         *               cancel: cancel
         *            }
         */
        const source = CancelToken.source();

        /**
         * 全局添加cancelToken
         * 建立一个全局变量用于保存未完成的请求列表
         * 当跳转到新页面，取消这些未完成的请求
         */

        /**
         * 因为post需要cancelToken参数
         * axios.post('/user/12345', {//post请求在第三个参数
         *            name: 'new name'
         *           }, {
         *            cancelToken: source.token
         *          });
         * @type {CancelToken}
         */
        config.cancelToken = source.token; // 因为post需要cancelToken参数

        /**
         * 全局保存请求，在router跳转页面的时候，全部取消
         * if(!a) { a = [] }
         * 等价于 a = ( a || [])
         * 等价于 a = a || []
         */
        Vue.prototype.__axiosPromiseRequestArray = ( Vue.prototype.__axiosPromiseRequestArray || [] );
        Vue.prototype.__axiosPromiseRequestArray.push(source.cancel);

        return config;
    },
    function (error) {
        // Do something with request error
        return Promise.reject(error);
    }
);

// Add a response interceptor
_axios.interceptors.response.use(
    /**
     * 非异常情况下调用此方法
     * @param response
     * @returns {AxiosResponse<any>}
     */
    function (response) {
        let operationResult = response.data;
        if (!operationResult) {
            throw new Error("NO DATA");
        }

        /**
         * 返回验证码时，是直接使用render方法，没有使用统一的ResultAssistor,所以需要判断是否存在operationResult.isOK
         * 如果不存在，就直接返回内容
         */
        if (operationResult.success != undefined && operationResult.success === false) {
            throw new Error(JSON.stringify(operationResult)); // 直接进入api方法的.catch(function(error) {}); 不会走拦截器error => {...}
        }

        return response;
    },
    /**
     * 不等于200 都走下面代码
     * @param error
     * @returns {Promise<never>|Promise<any>}
     */
    function (error) { /* onRejected */
        // Do something with response error
        if (axios.isCancel(error)) {
            console.log('Request canceled %s', error.message);
            /* 取消的情况下，终端Promise调用链 */
            return new Promise(() => {});
        }

        let msg = "";
        /* 进入此处，会在浏览器控制台提示错误 */
        let response = error.response;

        /* 拦截所有待catch的错误，这里统一进行message提示 */
        let elementui = Vue.prototype.$vue;

        if(!response) {
            elementui.$message.error("No response");
            return Promise.reject(error);
        }

        return Promise.reject(error);
    }
);

Plugin.install = function (Vue) {
    Vue.axios = _axios;
    window.axios = _axios;
    Object.defineProperties(Vue.prototype, {
        axios: {
            get() {
                return _axios;
            }
        },
        $axios: {
            get() {
                return _axios;
            }
        },
    });
};

Vue.use(Plugin)

export default Plugin;